package com.qzsoft.system.modules.zhjdsysdept.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qzsoft.jeemis.common.enums.SuperAdminEnum;
import com.qzsoft.jeemis.common.utils.Ten2ThirtyUtils;
import com.qzsoft.jeemis.platform.security.user.UserDetail;
import com.qzsoft.system.modules.zhjdsysdept.dto.ZhjdSysDeptTreeDto;
import com.qzsoft.system.modules.zhjdsysdept.entity.ZhjdSysDeptEntity;
import com.qzsoft.system.modules.zhjdsysdept.mapper.ZhjdSysDeptMapper;
import com.qzsoft.system.modules.zhjdsysdept.service.ZhjdSysDeptService;
import com.qzsoft.system.modules.zhjdsysdept.utils.ZhjdSysDeptConstants;
import com.qzsoft.system.repository.sys.dao.SysUserDao;
import com.qzsoft.system.repository.sys.entity.SysUserEntity;
import com.qzsoft.zhjd.common.annotation.ZhjdDataFilter;
import com.qzsoft.zhjd.common.components.BaseServiceComponent;
import com.qzsoft.zhjd.common.enums.BizCode;
import com.qzsoft.zhjd.common.utils.CodeCommonConstants;
import com.qzsoft.zhjd.common.utils.RenExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @ClassName ZhjdSysDeptServiceImpl
 * @Description 机构管理业务接口实现
 * @author linhuawei
 * @since 2021-12-01
 */
@Service
public class ZhjdSysDeptServiceImpl extends ServiceImpl<ZhjdSysDeptMapper, ZhjdSysDeptEntity>
        implements ZhjdSysDeptService {

    @Autowired
    private ZhjdSysDeptMapper zhjdSysDeptMapper;

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private BaseServiceComponent baseServiceComponent;

    @Override
    public List<ZhjdSysDeptTreeDto> treeAll() {
        // 获取当前用户机构作为机构根节点
        UserDetail user = baseServiceComponent.basegetLoginUser();
        String rootId = user.getDeptId();

        // 获取机构树
        QueryWrapper<ZhjdSysDeptEntity> query = new QueryWrapper<>();
        query.likeRight("id", rootId);
        query.orderByAsc("pid,sort");
        List<ZhjdSysDeptEntity> deptList = zhjdSysDeptMapper.selectList(query);

        // 转化为树状数据
        String pid = "";
        if (deptList.size() > 0) {
            pid = deptList.get(0).getPid();
        }
        return buildTree(deptList, pid);
    }

    /******************************** 组织结构功能 开始 **********************************/

    @Override
    public List<ZhjdSysDeptTreeDto> treeDept() {
        // 获取当前用户机构作为机构根节点
        UserDetail user = baseServiceComponent.basegetLoginUser();
        String rootId = user.getDeptId();

        // 获取机构树
        QueryWrapper<ZhjdSysDeptEntity> query = new QueryWrapper<>();
        query.ne("type", ZhjdSysDeptConstants.TYPE_BASE);
        query.likeRight("id", rootId);
        query.orderByAsc("pid,sort");
        List<ZhjdSysDeptEntity> deptList = zhjdSysDeptMapper.selectList(query);

        // 转化为树状数据
        String pid = "";
        if (deptList.size() > 0) {
            pid = deptList.get(0).getPid();
        }
        return buildTree(deptList, pid);
    }

    @Override
    public List<ZhjdSysDeptEntity> listDeptByPid(String pid) {
        // 普通管理员，只能查询所属机构及子机构的数据
        UserDetail user = baseServiceComponent.basegetLoginUser();
        String userDeptId = user.getDeptId();
        if (StringUtils.isBlank(pid)) {
            pid = userDeptId;
        }
        if (user.getSuperAdmin() == SuperAdminEnum.NO.value()) {
            if (pid.compareTo(userDeptId) > 0) {
                pid = userDeptId;
            }
        }
        // 查询机构列表
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("type", ZhjdSysDeptConstants.TYPE_BASE);
        queryWrapper.eq("pid", pid);
        queryWrapper.orderByAsc("pid,sort");
        return zhjdSysDeptMapper.selectList(queryWrapper);
    }

    @Override
    public ZhjdSysDeptEntity findDept(String pkId) {
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("type", ZhjdSysDeptConstants.TYPE_BASE);
        queryWrapper.eq("pkid", pkId);
        return zhjdSysDeptMapper.selectOne(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDept(ZhjdSysDeptEntity entity) {
        // 执行添加操作
        entity.setCode(null);
        entity.setSerial(null);
        entity.setPerson(null);
        entity.setPersonTel(null);
        entity.setStartTime(null);
        entity.setState(null);
        entity.setAddress(null);
        entity.setLatitude(null);
        entity.setLongitude(null);
        insert(entity);
    }

    @Override
    public void updateDept(ZhjdSysDeptEntity entity) {
        // 判断数据是否存在
        ZhjdSysDeptEntity temp = findDept(entity.getPkid());
        if (null == temp) {
            RenExceptionUtils.throwEx(BizCode.DATA_NOT_FOUND, "组织机构不存在");
        }

        // 执行修改操作
        entity.setType(temp.getType());
        entity.setHasLeaf(temp.getHasLeaf());
        entity.setSort(temp.getSort());
        entity.setCode(null);
        entity.setSerial(null);
        entity.setPerson(null);
        entity.setPersonTel(null);
        entity.setStartTime(null);
        entity.setState(null);
        entity.setAddress(null);
        entity.setLatitude(null);
        entity.setLongitude(null);
        update(temp, entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sortDept(String pkId1, String pkId2) {
        // 判断主键是否为空
        if (ObjectUtils.isEmpty(pkId1) || ObjectUtils.isEmpty(pkId2)) {
            return;
        }

        // 获取第一个机构排序信息
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pkid", pkId1).select("sort");
        ZhjdSysDeptEntity sysDeptEntity = zhjdSysDeptMapper.selectOne(queryWrapper);
        if (null == sysDeptEntity) {
            return;
        }
        String sort1 = sysDeptEntity.getSort();

        // 获取第二个机构排序信息
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pkid", pkId2).select("sort");
        sysDeptEntity = zhjdSysDeptMapper.selectOne(queryWrapper);
        if (null == sysDeptEntity) {
            return;
        }
        String sort2 = sysDeptEntity.getSort();

        // 修改第一个机构排序信息
        UpdateWrapper<ZhjdSysDeptEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("pkid", pkId1).set("sort", sort2);
        zhjdSysDeptMapper.update(null, updateWrapper);

        // 修改第二个机构排序信息
        updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("pkid", pkId2).set("sort", sort1);
        zhjdSysDeptMapper.update(null, updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteDept(String pkId) {
        // 判断数据是否存在
        ZhjdSysDeptEntity entity = findDept(pkId);
        if (null == entity) {
            RenExceptionUtils.throwEx(BizCode.DATA_NOT_FOUND, "组织机构不存在");
        }

        // 执行删除操作
        delete(entity);
    }

    /******************************** 组织结构功能 结束 **********************************/

    /******************************** 养护基地功能 开始 **********************************/

    @Override
    public IPage<ZhjdSysDeptEntity> pageForBase(Map<String, Object> params) {
        IPage<ZhjdSysDeptEntity> page = baseServiceComponent.getPage(params, ZhjdSysDeptEntity.class);
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<ZhjdSysDeptEntity>();
        if (ObjectUtils.isNotEmpty(params.get("name"))) {
            queryWrapper.like("name", params.get("name").toString());
        }
        if (ObjectUtils.isNotEmpty(params.get("state"))) {
            queryWrapper.like("state", params.get("state").toString());
        }
        queryWrapper.eq("type", ZhjdSysDeptConstants.TYPE_BASE);
        queryWrapper.orderByAsc("serial");
        return zhjdSysDeptMapper.selectPage(page, queryWrapper);
    }

    @Override
    @ZhjdDataFilter(baseCode = "code")
    public List<ZhjdSysDeptEntity> listForBase(Map<String, Object> params) {
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type", ZhjdSysDeptConstants.TYPE_BASE);
        if (ObjectUtils.isNotEmpty(params.get(ZhjdDataFilter.DATA_FILTER_SQL))) {
            queryWrapper.apply(params.get(ZhjdDataFilter.DATA_FILTER_SQL).toString());
        }
        queryWrapper.orderByAsc("serial");
        return zhjdSysDeptMapper.selectList(queryWrapper);
    }

    @Override
    public List<ZhjdSysDeptEntity> getAllBase() {
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<ZhjdSysDeptEntity>();
        queryWrapper.eq("type", ZhjdSysDeptConstants.TYPE_BASE);
        queryWrapper.orderByAsc("serial");
        return zhjdSysDeptMapper.selectList(queryWrapper);
    }

    @Override
    public ZhjdSysDeptEntity findBase(String pkId) {
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<ZhjdSysDeptEntity>();
        queryWrapper.eq("pkid", pkId);
        queryWrapper.eq("type", ZhjdSysDeptConstants.TYPE_BASE);
        return zhjdSysDeptMapper.selectOne(queryWrapper);
    }

    @Override
    public ZhjdSysDeptEntity getBaseByCode(String baseCode) {
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<ZhjdSysDeptEntity>();
        queryWrapper.eq("code", baseCode);
        queryWrapper.eq("type", ZhjdSysDeptConstants.TYPE_BASE);
        List<ZhjdSysDeptEntity> list = zhjdSysDeptMapper.selectList(queryWrapper);
        return null == list || 0 == list.size() ? null : list.get(0);
    }

    @Override
    public void saveBase(ZhjdSysDeptEntity entity) {
        // 判断编号是否重复
        String code = CodeCommonConstants.SYS_DEPT_CODE + entity.getCode();
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<ZhjdSysDeptEntity>();
        queryWrapper.eq("code", code);
        Integer count = zhjdSysDeptMapper.selectCount(queryWrapper);
        if (null != count && 0 < count) {
            RenExceptionUtils.throwEx("基地名编号[" + code + "]已存在！");
        }
        entity.setCode(code);

        // 执行添加操作
        insert(entity);
    }

    @Override
    public void updateBase(ZhjdSysDeptEntity entity) {
        // 判断数据是否存在
        ZhjdSysDeptEntity temp = findBase(entity.getPkid());
        if (null == temp) {
            RenExceptionUtils.throwEx(BizCode.DATA_NOT_FOUND, "组织机构不存在");
        }

        // 执行修改操作
        temp.setType(entity.getType());
        temp.setHasLeaf(entity.getHasLeaf());
        temp.setSort(entity.getSort());
//        temp.setNickCode(entity.getNickCode());
        update(temp, entity);
    }

    @Override
    public void deleteBase(String pkId) {
        // 判断养护基地是否存在
        ZhjdSysDeptEntity entity = findBase(pkId);
        if (null == entity) {
            RenExceptionUtils.throwEx(BizCode.DATA_NOT_FOUND, "养护基地信息不存在");
        }

        // 删除数据
        delete(entity);
    }

    /******************************** 养护基地功能 结束 **********************************/

    /**
     * @Title save
     * @Description 数据添加
     * @param entity 数据对象
     */
    private void insert(ZhjdSysDeptEntity entity) {
        // 判断名称是否重复
        QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", entity.getName());
        Integer count = zhjdSysDeptMapper.selectCount(queryWrapper);
        if (null != count && 0 < count) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "名称[" + entity.getName() + "]已经存在");
        }

        // TODO 养护基地不可添加下级？

        // 取父节点下最大机构ID
        String pid = entity.getPid();
        QueryWrapper<ZhjdSysDeptEntity> query = new QueryWrapper<>();
        query.eq("pid", pid).select("max(id) as id ");
        List<Map<String, Object>> mapList = zhjdSysDeptMapper.selectMaps(query);
        Integer id = 0;
        String strId = "";
        if (mapList.get(0) != null && mapList.size() > 0) {
            Object objValue = mapList.get(0).get("id");
            strId = String.valueOf(objValue);
            strId = strId.substring(strId.length() - 3);
            id = Ten2ThirtyUtils.thirtysixToTen(strId);
        }
        id++;
        strId = pid + Ten2ThirtyUtils.tenTo36(id, "000").toUpperCase();

        // 新的机构添加
        entity.setId(strId);
        entity.setSort(entity.getId());
        entity.setHasLeaf(true);

        // 执行更新操作
        zhjdSysDeptMapper.insert(entity);

        // 更新父节点的has_leaf 字段为0
        if (ObjectUtils.isNotEmpty(pid)) {
            UpdateWrapper<ZhjdSysDeptEntity> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", pid);
            updateWrapper.set("has_leaf", false);
            zhjdSysDeptMapper.update(null, updateWrapper);
        }
    }

    /**
     * @Title update
     * @Description 数据更新
     * @param temp   旧数据
     * @param entity 数据对象
     */
    private void update(ZhjdSysDeptEntity temp, ZhjdSysDeptEntity entity) {
        // 判断名称是否重复
        if (!temp.getName().equals(entity.getName())) {
            QueryWrapper<ZhjdSysDeptEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name", entity.getName());
            Integer count = zhjdSysDeptMapper.selectCount(queryWrapper);
            if (null != count && 0 < count) {
                RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "名称[" + entity.getName() + "]已经存在");
            }
        }

        // 执行更新操作
        zhjdSysDeptMapper.updateById(entity);
    }

    /**
     * @Title delete
     * @Description 数据删除
     * @param entity 数据对象
     */
    private void delete(ZhjdSysDeptEntity entity) {
        // 判断是否有子机构
        QueryWrapper<ZhjdSysDeptEntity> queryDept = new QueryWrapper<>();
        queryDept.eq("pid", entity.getId());
        Integer count = zhjdSysDeptMapper.selectCount(queryDept);
        if (null != count && 0 < count) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "当前有下属机构，不可删除");
        }

        // 判断机构下面是否有用户
        QueryWrapper<SysUserEntity> queryUser = new QueryWrapper<>();
        queryUser.eq("dept_pkid", entity.getPkid());
        count = sysUserDao.selectCount(queryUser);
        if (null != count && 0 < count) {
            RenExceptionUtils.throwEx(BizCode.PARAMS_ERROR, "当前有下属用户，不可删除");
        }

        // 执行删除操作
        zhjdSysDeptMapper.deleteById(entity.getPkid());

        // 判断当前节点下有无其他节点
        String pid = entity.getPid();
        if (ObjectUtils.isNotEmpty(pid)) {
            queryDept = new QueryWrapper<>();
            queryDept.eq("pid", pid);
            count = zhjdSysDeptMapper.selectCount(queryDept);

            // 执行更新操作
            UpdateWrapper<ZhjdSysDeptEntity> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", pid);
            updateWrapper.set("has_leaf", null == count || 0 == count);
            zhjdSysDeptMapper.update(null, updateWrapper);
        }
    }

    /**
     * @Title buildTree
     * @Description 转化树状数据
     * @param deptList 机构列表
     * @param pid      上级主键
     * @return 树状数据
     */
    private List<ZhjdSysDeptTreeDto> buildTree(List<ZhjdSysDeptEntity> deptList, String pid) {
        List<ZhjdSysDeptTreeDto> list = new ArrayList<>();
        List<ZhjdSysDeptTreeDto> children;
        ZhjdSysDeptTreeDto dto;
        ZhjdSysDeptEntity entity;
        for (int i = 0, len = deptList.size(); i < len; i++) {
            // 判断当前节点是否符合条件
            entity = deptList.get(i);
            if (!pid.equals(entity.getPid())) {
                continue;
            }

            // 转化数据对象
            dto = new ZhjdSysDeptTreeDto();
            BeanUtils.copyProperties(entity, dto);

            // 获取当前节点下级节点
            children = buildTree(deptList, entity.getId());
            if (null != children && 0 < children.size()) {
                dto.setChildren(children);
            }
            list.add(dto);
        }

        return list;
    }

}
